# DeepSeek App
import os
from typing import Dict, Tuple, List, Any
import requests
import json
import re
from openai import OpenAI
from apps.dsa.dsa_config import DsaConfig as DC
from apps.dsa.ds_fc_tools import DsFcTools


def get_weather000(city, date):
    base_url = "https://restapi.amap.com/v3/weather/weatherInfo"
    api_key =  '38f772fc39d8b002759c90b48ec9ca1b' # 高德API DeepSeekV3的API-KEY: https://console.amap.com/dev/key/app
    print(f'city: {city}; date: {date}; ????????????????????????????????')
    return json.dumps({
        '城市': city,
        '日期': date,
        '天气': '晴转多云'
    })
    # params = {
    #     'key': api_key,
    #     'city': city,
    #     'extensions': 'base',  # 可根据需求选择 'base' 或 'all'
    #     'output': 'json',
    #     'date': date  # 指定日期，格式如：2023-01-01
    # }
    
    # try:
    #     response = requests.get(base_url, params=params)
    #     data = response.json()
    #     # print(data) 
    #     if data['status'] == '1':
    #         weather_info = data['lives'][0]  # 如果选择了 'base' 扩展，使用 'lives'；选择 'all' 扩展，使用 'forecasts'
    #         # print(f"城市: {weather_info['city']}")
    #         # print(f"日期: {date}")
    #         # print(f"天气: {weather_info['weather']}")
    #         # print(f"温度: {weather_info['temperature']} ℃")
    #         # print(f"风力: {weather_info['windpower']} 级")
    #         rlt = json.dumps(weather_info)
    #         print(rlt)
    #         return rlt
    #     else:
    #         print("查询天气信息失败，错误码：" + data['infocode'])
    # except Exception as e:
    #     print("查询天气信息时发生错误：" + str(e))

class DsaApp(object):
    def __init__(self):
        self.name = 'apps.dsa.dsa_app.DsaApp'

    tools = [
        {
            "type": "function",
            "function": {
                "name": "DsFcTools__get_weather",
                "description": "查询指定城市，指定日期的天气情况",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "city": {
                            "type": "string",
                            "description": "要查询的城市名称，如：北京",
                        },
                        # "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
                        "date": {
                            "type": "string",
                            "description": "要查询的日期，示例：2023-11-23", 
                        }
                    },
                    "required": ["city", "date"],
                },
            },
        }
    ]
    
    @staticmethod
    def startup(params:Dict = {}) -> None:
        print(f'DeepSeek App v0.0.2')
        # DsaApp.hello_api(params=params)
        # DsaApp.multi_chat(params=params)
        DsaApp.function_calling(params=params)

    @staticmethod
    def function_calling(params:Dict = {}) -> None:
        print(f'工具调用示例')
        client = OpenAI(api_key=DC.API_KEY, base_url=DC.BASE_URL)
        ## 我们需要将用户的输入一并传递给OpenAI，以便从中提取函数调用所需要的参数。
        messages = [
                    {
                        "role": "user", 
                        "content": "北京2月7号天气怎么样"
                    }
                ]
        
        ### 第一次调用 Chat Completions API， 提取参数
        response = client.chat.completions.create(
                model="deepseek-chat",
                messages=messages,
                tools=DsaApp.tools,
                tool_choice="auto",  # auto is default, but we'll be explicit
            )
        response_message = response.choices[0].message
        tool_calls = response_message.tool_calls # 包含了函数调用所需要的信息
        if tool_calls:
            tool_call = tool_calls[0]
            # 大模型根据问题，传入的函数说明，拆分出调用函数的需要的两个参数
            function_args = json.loads(tool_call.function.arguments)
            # 将大模型传出的两个参数给到自己的函数，获取返回值
            function_response = DsFcTools.get_weather(
                city=function_args.get("city"),
                date=function_args.get("date"),
            )
            # 打印返回值
            # function_response
    
            function_name = tool_call.function.name
            messages.append(
                {
                    "tool_call_id": tool_call.id,
                    "role": "assistant",
                    "name": function_name,
                    "content": function_response,
                }
            )  # extend conversation with function response
    
            #再次调用模型，将message对象给大模型
            second_response = client.chat.completions.create(
                model="deepseek-chat",
                messages=messages,
            )  # get a new response from the model where it can see the function response

    @staticmethod
    def multi_chat(params:Dict = {}) -> None:
        print(f'多轮对话示例')
        client = OpenAI(api_key=DC.API_KEY, base_url=DC.BASE_URL)
        messages = []
        system_message = DsaApp.create_message('system', '你是清华大学电子系智能信号处理实验室智能化雷达方向教授')
        messages.append(system_message)
        while True:
            user_input = input('User: ')
            user_message = DsaApp.process_user_input(user_input)
            messages.append(user_message)
            assistant_reply = DsaApp.chat_with_deepseek(client, messages)
            print(f'assitant: {assistant_reply}')
            messages.append(DsaApp.create_message('assistant', assistant_reply))
            if user_input.lower() == 'exit':
                print(f'对话结束')
                break

    @staticmethod
    def extract_url_and_text(input_text:str) -> Tuple[str, Any]:
        url_pattern = re.compile(r'(https?://[^\s]+)')
        url_match = url_pattern.search(input_text)
        if url_match:
            url = url_match.group(0)
            description = input_text.replace(url, '').strip()
            return description, url
        else:
            return input_text, None

    @staticmethod
    def create_message(role:str, content:str) -> Dict:
        return {
            'role': role,
            'content': content
        }

    @staticmethod
    def process_user_input(input_text:str) -> Dict:
        description, url = DsaApp.extract_url_and_text(input_text=input_text)
        if url:
            if not description:
                description = '请帮我分析这张图片中的内容'
            return DsaApp.create_user_message_with_image(description, url)
        else:
            return DsaApp.create_message('user', input_text)

    @staticmethod
    def create_user_message_with_image(text:str, image_url:str) -> Dict:
        return {
            'role': 'user',
            'content': [
                {'type': 'text', 'text': text},
                {'type': 'image_url', 'image_url': {'url': image_url}}
            ]
        }

    @staticmethod
    def chat_with_deepseek(client:OpenAI, messages:List) -> str:
        response = client.chat.completions.create(
            model='deepseek-chat',
            messages=messages
        )
        return response.choices[0].message.content

    @staticmethod
    def hello_api(params:Dict = {}) -> None:
        client = OpenAI(api_key=DC.API_KEY, base_url=DC.BASE_URL)
        response = client.chat.completions.create(
            model = 'deepseek-chat',
            messages=[
                {'role': 'system', 'content': '你是清华大学电子系智能信号处理实验定智能化雷达领域教授'},
                {'role': 'user', 'content': '我是一名新入职清华大学电子系智能信号处理实验室的研究工程师，负责智能化雷达方向研发，想尽快发一篇SCI文章，请帮我选一些好研究主题和可投稿的期刊或顶会'}
            ],
            stream=False
        )
        print(response.choices[0].message.content)
